<!DOCTYPE html>
<html>
  <head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <meta name="description" content="tong.li&#39;s blog">
  <meta name="keyword" content="彤哥哥博客，95后技术爱好者,现就职于同程旅行/同程艺龙上海分公司，专注于互联网技术分享的平台。">
  
    <link rel="shortcut icon" href="/css/images/icon.png">
  
  <title>
    
      ElasticSearch之京东搜索实战 | 彤哥哥的博客
    
  </title>
  <link href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <link href="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.css" rel="stylesheet">
  <link href="https://cdn.staticfile.org/highlight.js/9.12.0/styles/tomorrow-night.min.css" rel="stylesheet">
  
<link rel="stylesheet" href="/css/style.css">

  
  <script src="https://cdn.staticfile.org/jquery/3.2.1/jquery.min.js"></script>
  <script src="https://cdn.staticfile.org/geopattern/1.2.3/js/geopattern.min.js"></script>
  <script src="https://cdn.staticfile.org/nprogress/0.2.0/nprogress.min.js"></script>
  
    
<script src="/js/qrious.js"></script>

  
  
  
  
    <!-- MathJax support START -->
    <script type="text/x-mathjax-config">
      MathJax.Hub.Config({
        tex2jax: {
          inlineMath: [ ['$','$'], ["\\(","\\)"]  ],
          processEscapes: true,
          skipTags: ['script', 'noscript', 'style', 'textarea', 'pre', 'code']
        }
      });
    </script>

    <script type="text/x-mathjax-config">
      MathJax.Hub.Queue(function() {
        var all = MathJax.Hub.getAllJax(), i;
        for (i=0; i < all.length; i += 1) {
          all[i].SourceElement().parentNode.className += ' has-jax';
        }
      });
    </script>
    <script type="text/javascript" src="https://cdn.staticfile.org/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    <!-- MathJax support END -->
  


  
  
    
<script src="/js/local-search.js"></script>


<meta name="generator" content="Hexo 5.4.2"></head>
<div class="wechat-share">
  <img src="/css/images/logo.png" />
</div>
  <body>
    <header class="header fixed-header">
  <div class="header-container">
    <a class="home-link" href="/">
      <div class="logo"></div>
      <span>彤哥哥的博客</span>
    </a>
    <ul class="right-list">
      
        <li class="list-item">
          
            <a href="/" class="item-link">主页</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/series/" class="item-link">分类</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/tags/" class="item-link">标签</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/archives/" class="item-link">归档</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/project/" class="item-link">项目</a>
          
        </li>
      
        <li class="list-item">
          
            <a href="/about/" class="item-link">关于</a>
          
        </li>
      
      
        <li class="menu-item menu-item-search right-list">
    <a role="button" class="popup-trigger">
        <i class="fa fa-search fa-fw"></i>
    </a>
</li>
      
    </ul>
    <div class="menu">
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
      <span class="icon-bar"></span>
    </div>
    <div class="menu-mask">
      <ul class="menu-list">
        
          <li class="menu-item">
            
              <a href="/" class="menu-link">主页</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/series/" class="menu-link">分类</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/tags/" class="menu-link">标签</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/archives/" class="menu-link">归档</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/project/" class="menu-link">项目</a>
            
          </li>
        
          <li class="menu-item">
            
              <a href="/about/" class="menu-link">关于</a>
            
          </li>
        
      </ul>
    </div>
    
      <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
            <span class="search-icon">
                <i class="fa fa-search"></i>
            </span>
            <div class="search-input-container">
                <input autocomplete="off" autocapitalize="off"
                    placeholder="Please enter your keyword(s) to search." spellcheck="false"
                    type="search" class="search-input">
            </div>
            <span class="popup-btn-close">
                <i class="fa fa-times-circle"></i>
            </span>
        </div>
        <div id="search-result">
            <div id="no-result">
                <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
            </div>
        </div>
    </div>
</div>
    
  </div>
</header>

    <div id="article-banner">
  <h2>ElasticSearch之京东搜索实战</h2>
  <p class="post-date">2020-12-04</p>
  <div class="arrow-down">
    <a href="javascript:;"></a>
  </div>
</div>
<main class="app-body flex-box">
  <!-- Article START -->
  <article class="post-article">
    <section class="markdown-content"><h1 id="1-前言"><a href="#1-前言" class="headerlink" title="1. 前言"></a>1. 前言</h1><p>​       最近学习了有关分布式搜索中间件**<a target="_blank" rel="noopener" href="https://www.elastic.co/cn/elasticsearch/">ElasticSearch</a>(简称ES)**相关知识，为了加强对ES基础知识的巩固，我耗时多日重新设计了一套京东商品搜索的小案例。</p>
<p>项目的整体架构前后端分离，前端采用Vue.js作为开发框架，后端用Spring Boot + ElasticSearch来完成搜索商品的API。在此次开发过程中，我将开发如下功能：</p>
<ol>
<li>前后端彻底的分离，前端采用Vue开发，后端采用Spring Boot 和ElasticSearch开发</li>
<li>京东商品数据的爬取采用Python的requests库和PyQuery库开发，并且翻页爬取全量数据</li>
<li>前端页面功能开发和优化，新增商品数据排序、滚动加载功能、回到顶部功能、异常处理弹框处理</li>
</ol>
<p>好了，话不多说，让我们就从此刻开始。</p>
<p><img src="https://i.loli.net/2020/12/12/L2ErDqZRbaB1nOf.png" alt="效果"></p>
<h1 id="2-前端页面准备"><a href="#2-前端页面准备" class="headerlink" title="2. 前端页面准备"></a>2. 前端页面准备</h1><h2 id="2-1-环境准备"><a href="#2-1-环境准备" class="headerlink" title="2.1 环境准备"></a>2.1 环境准备</h2><ul>
<li><p>node环境安装，读者<a target="_blank" rel="noopener" href="https://nodejs.org/zh-cn/">移步这里</a>自行安装，这里不过多累述，如已安装请直接跳过。</p>
</li>
<li><p>全局安装webpack，最新版为webpack4.x(升级问题比较多)，建议安装webpack3.x，如已安装请直接跳过。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g webpack@3</span><br></pre></td></tr></table></figure></li>
<li><p>全局安装Vue脚手架，如已安装请直接跳过。</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g @vue/cli</span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="2-2-搭建项目"><a href="#2-2-搭建项目" class="headerlink" title="2.2 搭建项目"></a>2.2 搭建项目</h2><ul>
<li><p>初始化项目</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">vue create jd-search <span class="comment"># 创建vue项目</span></span><br><span class="line"><span class="built_in">cd</span> jd-search <span class="comment"># 进入到项目根目录</span></span><br></pre></td></tr></table></figure></li>
<li><p>项目配置</p>
<ol>
<li><p>安装axios请求库</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install axios --save</span><br></pre></td></tr></table></figure></li>
<li><p>安装qs库用于url序列化</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install qs --save</span><br></pre></td></tr></table></figure></li>
<li><p>安装<a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN">Element-UI</a>组件库</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm i element-ui -S</span><br></pre></td></tr></table></figure></li>
<li><p>安装Element-UI滚动加载插件</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save vue-infinite-scroll</span><br></pre></td></tr></table></figure></li>
<li><p>在项目根目录下新建vue.config.js文件，配置项目启动后浏览器自动打开。具体代码如下：</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment"> * @Author: tong.li </span></span><br><span class="line"><span class="comment"> * @Date: 2020-12-04 15:23:34 </span></span><br><span class="line"><span class="comment"> * @Last Modified by: tong.li</span></span><br><span class="line"><span class="comment"> * @Last Modified time: 2020-12-04 15:23:57</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = &#123;</span><br><span class="line">    <span class="attr">devServer</span>: &#123;</span><br><span class="line">        <span class="comment">// 主机</span></span><br><span class="line">        <span class="attr">host</span>: <span class="string">&#x27;0.0.0.0&#x27;</span>,</span><br><span class="line">        <span class="comment">// 设置端口</span></span><br><span class="line">        <span class="attr">port</span>: <span class="number">8088</span>,</span><br><span class="line">        <span class="comment">// 自动打开浏览器</span></span><br><span class="line">        <span class="attr">open</span>: <span class="literal">true</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ol>
</li>
<li><p>启动测试</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run serve <span class="comment"># 启动稍等几秒后会自动打开浏览器，地址为http://127.0.0.1:8088</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="2-3-页面开发"><a href="#2-3-页面开发" class="headerlink" title="2.3 页面开发"></a>2.3 页面开发</h2><ul>
<li><p>静态资源导入</p>
<ol>
<li>在src/assets目录下新建css，导入style.css到src/assets/css目录下。</li>
<li>导入favicon.ico图标文件到public目录。</li>
<li>导入logo.png文件到src/assets目录。</li>
</ol>
</li>
<li><p>代码编写</p>
<ol>
<li><p>在项目新建src/plugins/element.js,按需导入Element-UI组件</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> &#123; <span class="title class_">Message</span>, <span class="title class_">Backtop</span> &#125; <span class="keyword">from</span> <span class="string">&#x27;element-ui&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;element-ui/lib/theme-chalk/index.css&#x27;</span></span><br><span class="line"><span class="keyword">import</span> infiniteScroll <span class="keyword">from</span> <span class="string">&#x27;vue-infinite-scroll&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 挂载滚动加载组件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(infiniteScroll)</span><br><span class="line"><span class="comment">// 挂载回到顶部组件</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="title function_">use</span>(<span class="title class_">Backtop</span>)</span><br><span class="line"><span class="comment">// 消息组件挂载</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$message</span> = <span class="title class_">Message</span></span><br></pre></td></tr></table></figure></li>
<li><p>在main.js利用vue的生命周期钩子函数初始化数据和基本配置</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">App</span> <span class="keyword">from</span> <span class="string">&#x27;./App.vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;./router&#x27;</span></span><br><span class="line"><span class="comment">// 导入CSS样式</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;./assets/css/style.css&#x27;</span></span><br><span class="line"><span class="comment">// 导入axios</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="comment">// 导入qs用于url序列化</span></span><br><span class="line"><span class="keyword">import</span> qs <span class="keyword">from</span> <span class="string">&#x27;qs&#x27;</span></span><br><span class="line"><span class="comment">// 导入Element-Ui组件</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;./plugins/element.js&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 配置请求根目录</span></span><br><span class="line">axios.<span class="property">defaults</span>.<span class="property">baseURL</span> = <span class="string">&#x27;http://localhocddst:9000/jd&#x27;</span></span><br><span class="line"><span class="comment">// 给Vue挂载axios</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$http</span> = axios</span><br><span class="line"><span class="comment">// 给Vue挂载qs</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$qs</span> = qs</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property">config</span>.<span class="property">productionTip</span> = <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  <span class="comment">// 通过mounted生命周期钩子初始化数据</span></span><br><span class="line">  <span class="attr">mounted</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 初始化品牌数据</span></span><br><span class="line">    <span class="keyword">const</span> initBrandList = [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;佳能&#x27;</span></span><br><span class="line">      &#125;, &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">2</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;尼康&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">3</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;索尼&#x27;</span>cdd</span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">4</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;哈苏&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">5</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;富士&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">6</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;莱卡&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">7</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;松下&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;v-<span class="keyword">if</span>=<span class="string">&quot;jdGoodsList !== null &amp;&amp; &#x27;list&#x27; in jdGoodsList &amp;&amp; jdGoodsList !== null&quot;</span></span><br><span class="line">        <span class="attr">id</span>: <span class="number">8</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;大疆&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">9</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;适马&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">10</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;松典&#x27;</span></span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">    <span class="comment">// 初始化排序数据</span></span><br><span class="line">    <span class="keyword">const</span> sortData = [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">0</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;综合&#x27;</span>,</span><br><span class="line">        <span class="attr">defaultDesc</span>: <span class="string">&#x27;true&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;人气&#x27;</span>,</span><br><span class="line">        <span class="attr">defaultDesc</span>: <span class="string">&#x27;true&#x27;</span></span><br><span class="line">      &#125;,v-<span class="keyword">if</span>=<span class="string">&quot;jdGoodsList !== null &amp;&amp; &#x27;list&#x27; in jdGoodsList &amp;&amp; jdGoodsList !== null&quot;</span></span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">2</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;价格&#x27;</span>,</span><br><span class="line">        <span class="attr">defaultDesc</span>: <span class="string">&#x27;false&#x27;</span></span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">    <span class="comment">// 初始化商品数据</span></span><br><span class="line">    <span class="keyword">const</span> initGoodsData = &#123;</span><br><span class="line">      <span class="comment">// 页码</span></span><br><span class="line">      <span class="attr">pageNum</span>: <span class="number">1</span>,</span><br><span class="line">      <span class="comment">// 页大小</span></span><br><span class="line">      <span class="attr">pageSize</span>: <span class="number">30</span>,</span><br><span class="line">      <span class="comment">// 当前页查询的列表个数</span></span><br><span class="line">      <span class="attr">size</span>: <span class="number">3</span>,</span><br><span class="line">      <span class="comment">// 查询总数</span></span><br><span class="line">      <span class="attr">total</span>: <span class="number">3</span>,</span><br><span class="line">      <span class="comment">// 总页数</span></span><br><span class="line">      <span class="attr">pages</span>: <span class="number">1</span>,</span><br><span class="line">      <span class="comment">// 数据</span></span><br><span class="line">      <span class="attr">list</span>: [</span><br><span class="line">        &#123;v-<span class="keyword">if</span>=<span class="string">&quot;jdGoodsList !== null &amp;&amp; &#x27;list&#x27; in jdGoodsList &amp;&amp; jdGoodsList !== null&quot;</span></span><br><span class="line">          <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line">          <span class="attr">sku</span>: <span class="string">&#x27;71806504602&#x27;</span>,</span><br><span class="line">          <span class="attr">title</span>: <span class="string">&#x27;佳能（Canon）EOS R5 全画幅专微旗舰 vlog微单相机 8K视频拍摄 微5 EOS R5&#x27;</span>,</span><br><span class="line">          <span class="attr">imgUrl</span>: <span class="string">&#x27;https://img12.360buyimg.com/n7/jfs/t1/147160/31/16416/248743/5fc60696E78885288/b3a05bc106140bfa.jpg&#x27;</span>,</span><br><span class="line">          <span class="attr">price</span>: <span class="number">26499.00</span>,</span><br><span class="line">          <span class="attr">shopName</span>: <span class="string">&#x27;彤哥哥相机铺&#x27;</span>,</span><br><span class="line">          <span class="attr">evaluationCount</span>: <span class="number">345</span>,</span><br><span class="line">          <span class="attr">transactionsCount</span>: <span class="number">578</span>,</span><br><span class="line">          <span class="attr">detailUrl</span>: <span class="string">&#x27;https://item.jd.com/71806504602.html&#x27;</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">id</span>: <span class="number">2</span>,</span><br><span class="line">          <span class="attr">sku</span>: <span class="string">&#x27;57690437524&#x27;</span>,</span><br><span class="line">          <span class="attr">title</span>: <span class="string">&#x27;索尼（SONY）a7r4/7RIV/ILCE-7RM4全画幅专业微单相机 单机身（不含镜头） &#x27;</span>,</span><br><span class="line">          <span class="attr">imgUrl</span>: <span class="string">&#x27;https://img14.360buyimg.com/n7/jfs/t1/146148/22/17013/313056/5fc9c999Ee3f824b0/5dfa0f48b6389d03.jpg&#x27;</span>,</span><br><span class="line">          <span class="attr">price</span>: <span class="number">19185.00</span>,</span><br><span class="line">          <span class="attr">shopName</span>: <span class="string">&#x27;彤哥哥相机铺&#x27;</span>,</span><br><span class="line">          <span class="attr">evaluationCount</span>: <span class="number">781</span>,</span><br><span class="line">          <span class="attr">transactionsCount</span>: <span class="number">233</span>,</span><br><span class="line">          <span class="attr">detailUrl</span>: <span class="string">&#x27;https://item.jd.com/57690437524.html&#x27;</span></span><br><span class="line">        &#125;,</span><br><span class="line">        &#123;</span><br><span class="line">          <span class="attr">id</span>: <span class="literal">null</span>,</span><br><span class="line">          <span class="attr">sku</span>: <span class="string">&#x27;10024727923051&#x27;</span>,</span><br><span class="line">          <span class="attr">title</span>: <span class="string">&#x27;拍拍华为HUAWEIP40Pro+5G手机华为二手手机大陆国行陶瓷白8G+256G&#x27;</span>,</span><br><span class="line">          <span class="attr">imgUrl</span>: <span class="string">&#x27;https://img11.360buyimg.com/n7/jfs/t1/155325/20/8861/135429/5fced890Eccce267c/dc50f6ee27eb47ff.jpg&#x27;</span>,</span><br><span class="line">          <span class="attr">price</span>: <span class="string">&#x27;5599.00&#x27;</span>,</span><br><span class="line">          <span class="attr">shopName</span>: <span class="string">&#x27;拍拍二手官方旗舰店&#x27;</span>,</span><br><span class="line">          <span class="attr">evaluationCount</span>: <span class="number">16224</span>,</span><br><span class="line">          <span class="attr">transactionsCount</span>: <span class="number">677</span>,</span><br><span class="line">          <span class="attr">detailUrl</span>: <span class="string">&#x27;https://item.jd.com/10024727923051.html&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">      ]</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(<span class="string">&#x27;initGoodsData&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(initGoodsData))</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(<span class="string">&#x27;initBrandList&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(initBrandList))</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(<span class="string">&#x27;sortData&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(sortData))</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 通过mounted生命周期钩子清除初始化数据</span></span><br><span class="line">  <span class="attr">destroyed</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">removeItem</span>(<span class="string">&#x27;initGoodsData&#x27;</span>)</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">removeItem</span>(<span class="string">&#x27;brandList&#x27;</span>)</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">removeItem</span>(<span class="string">&#x27;sortData&#x27;</span>)</span><br><span class="line">  &#125;,</span><br><span class="line">  router,</span><br><span class="line">  <span class="attr">render</span>: <span class="function"><span class="params">h</span> =&gt;</span> <span class="title function_">h</span>(<span class="title class_">App</span>)</span><br><span class="line">&#125;).$mount(<span class="string">&#x27;#app&#x27;</span>)</span><br></pre></td></tr></table></figure></li>
<li><p>在components文件下新建Search.vue，编写页面组件</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;page&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;mallPage&quot;</span> <span class="attr">class</span>=<span class="string">&quot; mallist tmall- page-not-market &quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 头部搜索 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;header&quot;</span> <span class="attr">class</span>=<span class="string">&quot; header-list-app&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;headerLayout&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;headerCon &quot;</span>&gt;</span></span><br><span class="line">                    <span class="comment">&lt;!-- Logo--&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">h1</span> <span class="attr">id</span>=<span class="string">&quot;mallLogo&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">img</span> <span class="attr">th:src</span>=<span class="string">&quot;../static/images/jdlogo.png&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"></span><br><span class="line">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;header-extra&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">                        <span class="comment">&lt;!--搜索--&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;mallSearch&quot;</span> <span class="attr">class</span>=<span class="string">&quot;mall-search&quot;</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">form</span> <span class="attr">name</span>=<span class="string">&quot;searchTop&quot;</span> <span class="attr">class</span>=<span class="string">&quot;mallSearch-form clearfix&quot;</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">fieldset</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">legend</span>&gt;</span>天猫搜索<span class="tag">&lt;/<span class="name">legend</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;mallSearch-input clearfix&quot;</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;s-combobox&quot;</span> <span class="attr">id</span>=<span class="string">&quot;s-combobox-685&quot;</span>&gt;</span></span><br><span class="line">                                            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;s-combobox-input-wrap&quot;</span>&gt;</span></span><br><span class="line">                                                <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">autocomplete</span>=<span class="string">&quot;off&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;params.keywords&quot;</span> <span class="attr">id</span>=<span class="string">&quot;mq&quot;</span></span></span><br><span class="line"><span class="tag">                                                       <span class="attr">class</span>=<span class="string">&quot;s-combobox-input&quot;</span> <span class="attr">aria-haspopup</span>=<span class="string">&quot;true&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;请输入关键字&quot;</span>&gt;</span></span><br><span class="line">                                            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">id</span>=<span class="string">&quot;searchbtn&quot;</span>  @<span class="attr">click.prevent</span>=<span class="string">&quot;doSearch(params.keywords)&quot;</span>&gt;</span>搜索<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">fieldset</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;relKeyTop&quot;</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥相机专场<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥聊Java<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥摄影大讲堂<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥电脑修理铺<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥图书<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 商品详情页面 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main&quot;</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!-- 品牌分类 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">form</span> <span class="attr">class</span>=<span class="string">&quot;navAttrsForm&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;attrs j_NavAttrs&quot;</span> <span class="attr">style</span>=<span class="string">&quot;display:block&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;brandAttr j_nav_brand&quot;</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;j_Brand attr&quot;</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;attrKey&quot;</span>&gt;</span></span><br><span class="line">                                    你可能要搜</span><br><span class="line">                                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;attrValues&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;av-collapse row-2&quot;</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;brand in brandList&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;brand.id&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;doSearch(brand.name)&quot;</span>&gt;</span></span><br><span class="line">                                            <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span>&gt;</span>&#123;&#123;brand.name&#125;&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"></span><br><span class="line">                <span class="comment">&lt;!-- 排序规则 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;filter clearfix&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-for</span>=<span class="string">&quot;sortItem in sortData&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;sortItem.id&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;doSortSearch(sortItem.id,sortItem.defaultDesc)&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;fSort&quot;</span> <span class="attr">:class</span>=<span class="string">&quot;&#123;&#x27;fSort-cur&#x27;: sortItem.id == defaultSortNumber&#125;&quot;</span>&gt;</span></span><br><span class="line">                        &#123;&#123;sortItem.name&#125;&#125;</span><br><span class="line">                        <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-if</span>=<span class="string">&quot;sortItem.id &gt; 1&quot;</span>&gt;</span></span><br><span class="line">                            <span class="comment">&lt;!-- 排序上标志，阻止向父级冒泡 --&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;f-ico-triangle-mt&quot;</span> <span class="attr">:style</span>=<span class="string">&quot;sortViewFlag==1 ? &#123;&#x27;border-bottom&#x27;: &#x27;4px solid red&#x27;&#125; : &#123;&#125;&quot;</span> @<span class="attr">click.stop</span>=<span class="string">&quot;doSortSearch(sortItem.id,false)&quot;</span> &gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">                            <span class="comment">&lt;!-- 排序下标志，阻止向父级冒泡 --&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;f-ico-triangle-mb&quot;</span> <span class="attr">:style</span>=<span class="string">&quot;sortViewFlag==2 ? &#123;&#x27;border-top&#x27;: &#x27;4px solid red&#x27;&#125; : &#123;&#125;&quot;</span>  @<span class="attr">click.stop</span>=<span class="string">&quot;doSortSearch(sortItem.id,true)&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-else</span>&gt;</span></span><br><span class="line">                           <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;f-ico-arrow-d&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!-- 商品详情 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;view grid-nosku&quot;</span> <span class="attr">v-if</span>=<span class="string">&quot;jdGoodsList !== null &amp;&amp; &#x27;list&#x27; in jdGoodsList &amp;&amp; jdGoodsList !== null&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;product&quot;</span>  <span class="attr">v-for</span>=<span class="string">&quot;goods in jdGoodsList.list&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;goods.id&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">a</span> <span class="attr">:href</span>=<span class="string">&quot;goods.detailUrl&quot;</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;product-iWrap&quot;</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!--商品封面--&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;productImg-wrap&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;productImg&quot;</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;<span class="name">img</span> <span class="attr">:src</span>=<span class="string">&quot;goods.imgUrl&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!--价格--&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;productPrice&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">em</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>¥<span class="tag">&lt;/<span class="name">b</span>&gt;</span>&#123;&#123;goods.price&#125;&#125;<span class="tag">&lt;/<span class="name">em</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!--标题--&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;productTitle&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="comment">&lt;!-- 使用v-html原因是高亮渲染 --&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">a</span>  <span class="attr">v-html</span>=<span class="string">&quot;goods.title&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!-- 店铺名 --&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;productShop&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">span</span>&gt;</span>店铺：&#123;&#123;goods.shopName&#125;&#125; <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!-- 成交信息 --&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;productStatus&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">span</span>&gt;</span>月成交<span class="tag">&lt;<span class="name">em</span>&gt;</span>&#123;&#123;goods.transactionsCount&#125;&#125;笔<span class="tag">&lt;/<span class="name">em</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">span</span>&gt;</span>评价 <span class="tag">&lt;<span class="name">a</span>&gt;</span>&#123;&#123;goods.evaluationCount&#125;&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                         <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">name</span>: <span class="string">&#x27;Search&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">  data () &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">sortData</span>: <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;sortData&#x27;</span>)),</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">brandList</span>: <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;initBrandList&#x27;</span>)),</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">keywords</span>: <span class="string">&#x27;&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">jdGoodsList</span>: <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;initGoodsData&#x27;</span>)),</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">defaultSortNumber</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">sortViewFlag</span>: <span class="number">0</span></span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;,</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">  &#125;,</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">    doSearch (keywords) &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 搜索操作</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (keywords.<span class="title function_">trim</span>() === <span class="string">&#x27;&#x27;</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span></span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// TODO 请求后端接口</span></span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">jdGoodsList</span> = []</span></span><br><span class="line"><span class="language-javascript">    &#125;,</span></span><br><span class="line"><span class="language-javascript">    doSortSearch (id, defaultDesc) &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 排序字段置为选中</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (id === <span class="number">2</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 排序箭头置为选中</span></span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="property">sortViewFlag</span> = !defaultDesc ? <span class="number">1</span> : <span class="number">2</span></span></span><br><span class="line"><span class="language-javascript">        defaultDesc = (<span class="variable language_">this</span>.<span class="property">sortViewFlag</span> === <span class="number">2</span>)</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">defaultSortNumber</span> = id</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 重新设置排序号和排序规则</span></span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">sortNumber</span> = id</span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">isDesc</span> = defaultDesc</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 执行搜索</span></span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="title function_">doSearch</span>(<span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">keywords</span>)</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;,</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="string">&#x27;params.keywords&#x27;</span>: <span class="keyword">function</span> (<span class="params">newVal</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 若不搜索，则默认显示LocalStorage存储的商品信息</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (newVal === <span class="string">&#x27;&#x27;</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="property">jdGoodsList</span> = <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;initGoodsData&#x27;</span>))</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;</span></span><br><span class="line"><span class="language-javascript">&#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span> <span class="attr">lang</span>=<span class="string">&quot;scss&quot;</span> <span class="attr">scope</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
<li><p>在App.vue进行组件渲染</p>
<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">Search</span>/&gt;</span></span><br><span class="line">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"><span class="keyword">import</span> <span class="title class_">Search</span> <span class="keyword">from</span> <span class="string">&#x27;./components/Search.vue&#x27;</span></span></span><br><span class="line"><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">name</span>: <span class="string">&#x27;App&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">components</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="title class_">Search</span></span></span><br><span class="line"><span class="language-javascript">  &#125;</span></span><br><span class="line"><span class="language-javascript">&#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span> <span class="attr">lang</span>=<span class="string">&quot;scss&quot;</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
</ol>
</li>
<li><p>启动测试</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run serve <span class="comment"># 启动后会自动打开浏览器</span></span><br></pre></td></tr></table></figure></li>
<li><p>查看页面效果</p>
<p><img src="https://ltyeamin.github.io/imgs/2020/12/20201207151010.gif" alt="搜索页面效果图"></p>
</li>
</ul>
<h1 id="3-京东数据爬取"><a href="#3-京东数据爬取" class="headerlink" title="3. 京东数据爬取"></a>3. 京东数据爬取</h1><ul>
<li><p>安装<a target="_blank" rel="noopener" href="https://www.elastic.co/cn/downloads/elasticsearch">ElasticSearch</a>7.x以及<a target="_blank" rel="noopener" href="https://github.com/mobz/elasticsearch-head">Head</a>插件和<a target="_blank" rel="noopener" href="https://github.com/medcl/elasticsearch-analysis-ik">IK中文分词</a>插件，安装后并启动ElasticSearch</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.10.0/elasticsearch-analysis-ik-7.10.0.zip  <span class="comment">#安装IK分词器</span></span><br></pre></td></tr></table></figure></li>
<li><p>在git bash命令行执行如下命令来创建索引，自定义mapping，主要是为了设置中文分词</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line">curl -X PUT <span class="string">&quot;localhost:9200/jd_goods&quot;</span> -H <span class="string">&#x27;Content-Type: application/json&#x27;</span> -d \</span><br><span class="line"><span class="string">&#x27;</span></span><br><span class="line"><span class="string">&#123;</span></span><br><span class="line"><span class="string">    &quot;mappings&quot;: &#123;</span></span><br><span class="line"><span class="string">        &quot;properties&quot;: &#123;</span></span><br><span class="line"><span class="string">            &quot;id&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;long&quot;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &quot;sku&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;text&quot;,</span></span><br><span class="line"><span class="string">                &quot;analyzer&quot;: &quot;ik_max_word&quot;,</span></span><br><span class="line"><span class="string">                &quot;search_analyzer&quot;: &quot;ik_max_word&quot;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &quot;title&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;text&quot;,</span></span><br><span class="line"><span class="string">                &quot;analyzer&quot;: &quot;ik_max_word&quot;,</span></span><br><span class="line"><span class="string">                &quot;search_analyzer&quot;: &quot;ik_max_word&quot;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &quot;imgUrl&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;text&quot;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &quot;price&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;double&quot;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &quot;evaluationCount&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;integer&quot;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &quot;transactionsCount&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;integer&quot;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &quot;shopName&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;text&quot;,</span></span><br><span class="line"><span class="string">                &quot;analyzer&quot;: &quot;ik_max_word&quot;,</span></span><br><span class="line"><span class="string">                &quot;search_analyzer&quot;: &quot;ik_max_word&quot;</span></span><br><span class="line"><span class="string">            &#125;,</span></span><br><span class="line"><span class="string">            &quot;detailUrl&quot;: &#123;</span></span><br><span class="line"><span class="string">                &quot;type&quot;: &quot;text&quot;</span></span><br><span class="line"><span class="string">            &#125;</span></span><br><span class="line"><span class="string">        &#125;</span></span><br><span class="line"><span class="string">    &#125;</span></span><br><span class="line"><span class="string">&#125;</span></span><br><span class="line"><span class="string">&#x27;</span></span><br></pre></td></tr></table></figure></li>
<li><p>安装Python环境以及脚本所需要的依赖库</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip install -r requirements.txt <span class="comment"># 安装项目依赖</span></span><br></pre></td></tr></table></figure></li>
<li><p>爬取代码</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#!/usr/bin python3.6</span></span><br><span class="line"><span class="comment"># -*- encoding: utf-8 -*-</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="string">@File    : __init__.py.py</span></span><br><span class="line"><span class="string">@Description : 爬取京东商品数据</span></span><br><span class="line"><span class="string">@Author  : tong.li</span></span><br><span class="line"><span class="string">@Email   : lt_alex@163.com</span></span><br><span class="line"><span class="string">@Blog    : https://ltalex.gitee.io</span></span><br><span class="line"><span class="string">@Time    : 2020/12/6 下午8:31</span></span><br><span class="line"><span class="string">&quot;&quot;&quot;</span></span><br><span class="line"><span class="keyword">import</span> requests</span><br><span class="line"><span class="keyword">from</span> pyquery <span class="keyword">import</span> PyQuery <span class="keyword">as</span> pq</span><br><span class="line"><span class="keyword">import</span> time</span><br><span class="line"><span class="keyword">from</span> requests.exceptions <span class="keyword">import</span> RequestException</span><br><span class="line"><span class="keyword">import</span> re</span><br><span class="line"><span class="keyword">from</span> elasticsearch <span class="keyword">import</span> Elasticsearch</span><br><span class="line"><span class="keyword">from</span> elasticsearch <span class="keyword">import</span> helpers</span><br><span class="line"><span class="keyword">import</span> json</span><br><span class="line"><span class="keyword">import</span> random</span><br><span class="line"></span><br><span class="line"><span class="comment"># 连接ElasticSearch</span></span><br><span class="line">es = Elasticsearch(</span><br><span class="line">    [<span class="string">&#x27;127.0.0.1&#x27;</span>],</span><br><span class="line">    port=<span class="number">9200</span></span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">request_page</span>(<span class="params">url</span>):</span><br><span class="line">    <span class="keyword">try</span>:</span><br><span class="line">        <span class="comment"># 设置请求头</span></span><br><span class="line">        headers = &#123;</span><br><span class="line">            <span class="string">&#x27;User-Agent&#x27;</span> : <span class="string">&#x27;Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36&#x27;</span></span><br><span class="line">        &#125;</span><br><span class="line">        datas = []</span><br><span class="line">        response = requests.get(url, headers=headers)</span><br><span class="line">        <span class="keyword">if</span> response.status_code == <span class="number">200</span>:</span><br><span class="line">            text = response.text</span><br><span class="line">            <span class="comment"># 获取京东商品数据</span></span><br><span class="line">            doc = pq(text)</span><br><span class="line">            lis = doc(<span class="string">&#x27;div#J_goodsList li[data-sku]&#x27;</span>).items()</span><br><span class="line"></span><br><span class="line">            <span class="keyword">for</span> index,li <span class="keyword">in</span> <span class="built_in">enumerate</span>(lis) : </span><br><span class="line">                goods =  &#123;</span><br><span class="line">                    <span class="comment"># ID=微秒级时间戳+索引</span></span><br><span class="line">                    <span class="string">&#x27;id&#x27;</span>: <span class="built_in">int</span>(<span class="built_in">round</span>(time.time() * <span class="number">1000000</span>)) + index,</span><br><span class="line">                    <span class="comment">#SKU</span></span><br><span class="line">                    <span class="string">&#x27;sku&#x27;</span>: li.attr(<span class="string">&#x27;data-sku&#x27;</span>),</span><br><span class="line">                    <span class="comment">#  名称,正则替换掉不需要的空格</span></span><br><span class="line">                    <span class="string">&#x27;title&#x27;</span>: re.sub(<span class="string">&#x27;\\s&#123;2,&#125;|\\n*&#x27;</span>,<span class="string">&#x27;&#x27;</span>,li(<span class="string">&#x27;.p-name em&#x27;</span>).text()),</span><br><span class="line">                    <span class="comment">#  图片</span></span><br><span class="line">                    <span class="string">&#x27;imgUrl&#x27;</span>: <span class="string">&#x27;https:&#x27;</span> + li(<span class="string">&#x27;.p-img img&#x27;</span>).attr(<span class="string">&#x27;data-lazy-img&#x27;</span>),</span><br><span class="line">                    <span class="comment"># 价格</span></span><br><span class="line">                    <span class="string">&#x27;price&#x27;</span>: <span class="built_in">float</span>(<span class="number">0.0</span> <span class="keyword">if</span> li(<span class="string">&#x27;.p-price i&#x27;</span>).text() == <span class="string">&#x27;免费&#x27;</span> <span class="keyword">else</span> li(<span class="string">&#x27;.p-price i&#x27;</span>).text()),</span><br><span class="line">                    <span class="comment"># 店铺名称</span></span><br><span class="line">                    <span class="string">&#x27;shopName&#x27;</span>: li(<span class="string">&#x27;.p-shop span&#x27;</span>).text(),</span><br><span class="line">                    <span class="comment"># 评价数,随机生成</span></span><br><span class="line">                    <span class="string">&#x27;evaluationCount&#x27;</span>: random.randint(<span class="number">100</span>,<span class="number">99999</span>),</span><br><span class="line">                     <span class="comment"># 成交数,随机生成</span></span><br><span class="line">                    <span class="string">&#x27;transactionsCount&#x27;</span>: random.randint(<span class="number">100</span>,<span class="number">9999</span>),</span><br><span class="line">                    <span class="comment"># 跳转到的商品详情地址</span></span><br><span class="line">                    <span class="string">&#x27;detailUrl&#x27;</span>: <span class="string">&#x27;https:&#x27;</span> +  li(<span class="string">&#x27;.p-img a&#x27;</span>).attr(<span class="string">&#x27;href&#x27;</span>)</span><br><span class="line">                &#125;</span><br><span class="line">                datas.append(goods)</span><br><span class="line">            <span class="keyword">return</span> datas</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">None</span></span><br><span class="line">    <span class="keyword">except</span> RequestException:</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">None</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 存储到:ElasticSearch</span></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">storeToES</span>(<span class="params">datas</span>):</span><br><span class="line">    actions = []</span><br><span class="line">    <span class="keyword">for</span> data <span class="keyword">in</span> datas:</span><br><span class="line">        action = &#123;</span><br><span class="line">            <span class="string">&#x27;_index&#x27;</span>:<span class="string">&#x27;jd_goods&#x27;</span>, <span class="comment">#索引名称</span></span><br><span class="line">            <span class="string">&#x27;_source&#x27;</span>: data</span><br><span class="line">        &#125;</span><br><span class="line">        actions.append(action)</span><br><span class="line">    helpers.bulk(es, actions)</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">getData</span>(<span class="params">url</span>):</span><br><span class="line">    datas = request_page(url)</span><br><span class="line">    <span class="comment"># 往ES批量插入数据</span></span><br><span class="line">    <span class="keyword">if</span> <span class="built_in">len</span>(datas) != <span class="number">0</span> : &#123;</span><br><span class="line">        storeToES(datas)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">print</span>(json.dumps(datas,ensure_ascii=<span class="literal">False</span>))</span><br><span class="line">    <span class="built_in">print</span>(<span class="string">&#x27;-&#x27;</span> * <span class="number">200</span>)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    <span class="comment"># 爬取京东商品数据</span></span><br><span class="line">    keywords = <span class="string">&quot;相机&quot;</span> <span class="comment"># 关键字信息，相当于京东搜索输入框</span></span><br><span class="line">    url = <span class="string">&#x27;https://search.jd.com/Search?keyword=&#x27;</span>+keywords+<span class="string">&#x27;&amp;enc=utf-8&amp;page=&#x27;</span></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="number">100</span>):</span><br><span class="line">        getData(url + <span class="built_in">str</span>(i+<span class="number">1</span>))</span><br><span class="line">        <span class="comment"># 京东有反爬虫限制,爬的太多会有IP或验证码限制,等待0.5毫秒再次请求</span></span><br><span class="line">        time.sleep(<span class="number">0.5</span>)</span><br></pre></td></tr></table></figure></li>
<li><p>运行爬虫</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">python jd-goods-crawler.py <span class="comment"># jd-goods-crawler.py为上述爬取代码的文件名</span></span><br></pre></td></tr></table></figure></li>
<li><p>启动运行</p>
<p><img src="https://ltyeamin.github.io/imgs/2020/12/20201211132607.gif" alt="京东数据爬取"></p>
</li>
<li><p>ES查看索引数据</p>
<p>​    <img src="https://ltyeamin.github.io/imgs/2020/12/20201208164051.png" alt="image-20201208164051555"></p>
</li>
</ul>
<h1 id="4-后端接口开发"><a href="#4-后端接口开发" class="headerlink" title="4. 后端接口开发"></a>4. 后端接口开发</h1><h2 id="4-1-环境准备"><a href="#4-1-环境准备" class="headerlink" title="4.1 环境准备"></a>4.1 环境准备</h2><ul>
<li>配置JDK和Java环境变量，建议安装JDK8版本</li>
<li>准备一个IDE，<a target="_blank" rel="noopener" href="https://www.eclipse.org/downloads/">Eclipse</a>或者<a target="_blank" rel="noopener" href="https://www.jetbrains.com/idea/">IntelliJ IDEA</a>都可以，我这里是<a target="_blank" rel="noopener" href="https://www.jetbrains.com/idea/">IntelliJ IDEA</a></li>
</ul>
<h2 id="4-2-项目搭建"><a href="#4-2-项目搭建" class="headerlink" title="4.2 项目搭建"></a>4.2 项目搭建</h2><ul>
<li>方式一： 通过在线的web工具<a target="_blank" rel="noopener" href="https://start.spring.io/">Spring Initializr</a>初始化Spring Boot项目</li>
<li>方式二: 通过IDEA新建项目中的Spring Initialzr初始化Spring Boot项目</li>
</ul>
<h2 id="4-3-接口开发"><a href="#4-3-接口开发" class="headerlink" title="4.3 接口开发"></a>4.3 接口开发</h2><ul>
<li><p>依赖导入，我这里是用Gradle构建的项目</p>
<figure class="highlight groovy"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">plugins &#123;</span><br><span class="line">    id <span class="string">&#x27;org.springframework.boot&#x27;</span> version <span class="string">&#x27;2.4.0&#x27;</span></span><br><span class="line">    id <span class="string">&#x27;io.spring.dependency-management&#x27;</span> version <span class="string">&#x27;1.0.10.RELEASE&#x27;</span></span><br><span class="line">    id <span class="string">&#x27;java&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">group = <span class="string">&#x27;com.jd&#x27;</span></span><br><span class="line">version = <span class="string">&#x27;0.0.1-SNAPSHOT&#x27;</span></span><br><span class="line">sourceCompatibility = <span class="string">&#x27;1.8&#x27;</span></span><br><span class="line"></span><br><span class="line">configurations &#123;</span><br><span class="line">    compileOnly &#123;</span><br><span class="line">        extendsFrom annotationProcessor</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">repositories &#123;</span><br><span class="line">    mavenLocal() <span class="comment">//直接使用本地maven仓库</span></span><br><span class="line">    maven &#123;    <span class="comment">// 镜像源采用阿里云，加速依赖下载</span></span><br><span class="line">        url <span class="string">&#x27;https://maven.aliyun.com/repository/public&#x27;</span></span><br><span class="line">    &#125;</span><br><span class="line">    mavenCentral() <span class="comment">// 使用中央仓库</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">dependencies &#123;</span><br><span class="line">    <span class="comment">// Web相关依赖</span></span><br><span class="line">    implementation <span class="string">&#x27;org.springframework.boot:spring-boot-starter-web&#x27;</span></span><br><span class="line">    <span class="comment">// ElasticSearch相关依赖</span></span><br><span class="line">    implementation <span class="string">&#x27;org.springframework.boot:spring-boot-starter-data-elasticsearch&#x27;</span></span><br><span class="line">    <span class="comment">// 分页插件</span></span><br><span class="line">    implementation <span class="string">&#x27;com.github.pagehelper:pagehelper:5.1.2&#x27;</span></span><br><span class="line">    compileOnly <span class="string">&#x27;org.projectlombok:lombok&#x27;</span></span><br><span class="line">    annotationProcessor <span class="string">&#x27;org.projectlombok:lombok&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">test &#123;</span><br><span class="line">    useJUnitPlatform()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>项目配置application.yml</p>
<figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">server:</span></span><br><span class="line">  <span class="attr">port:</span> <span class="number">9000</span>   <span class="comment"># 项目端口号配置</span></span><br><span class="line"><span class="attr">spring:</span></span><br><span class="line">  <span class="attr">elasticsearch:</span>  <span class="comment"># ElasticSearch配置</span></span><br><span class="line">    <span class="attr">rest:</span></span><br><span class="line">      <span class="attr">uris:</span> <span class="string">http://127.0.0.1:9200</span></span><br></pre></td></tr></table></figure></li>
<li><p>全局跨域配置</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.jd.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> javax.servlet.*;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletRequest;</span><br><span class="line"><span class="keyword">import</span> javax.servlet.http.HttpServletResponse;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@projectName</span>: jd-search-api</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@className</span>: com.jd.config.GlobalCorsFilter</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span>: 全局跨域配置</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: tong.li</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@createTime</span>: 2020/12/10 20:16</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span>: v1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@copyright</span>: 版权所有 © 李彤</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GlobalCorsFilter</span> <span class="keyword">implements</span> <span class="title class_">Filter</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">doFilter</span><span class="params">(ServletRequest req, ServletResponse res, FilterChain chain)</span> <span class="keyword">throws</span> IOException, ServletException &#123;</span><br><span class="line">        <span class="type">HttpServletResponse</span> <span class="variable">response</span> <span class="operator">=</span> (HttpServletResponse) res;</span><br><span class="line">        <span class="type">HttpServletRequest</span> <span class="variable">reqs</span> <span class="operator">=</span> (HttpServletRequest) req;</span><br><span class="line">        response.setHeader(<span class="string">&quot;Access-Control-Allow-Origin&quot;</span>,reqs.getHeader(<span class="string">&quot;Origin&quot;</span>));</span><br><span class="line">        response.setHeader(<span class="string">&quot;Access-Control-Allow-Credentials&quot;</span>, <span class="string">&quot;true&quot;</span>);</span><br><span class="line">        response.setHeader(<span class="string">&quot;Access-Control-Allow-Methods&quot;</span>, <span class="string">&quot;POST, GET, OPTIONS, DELETE,PUT&quot;</span>);</span><br><span class="line">        response.setHeader(<span class="string">&quot;Access-Control-Max-Age&quot;</span>, <span class="string">&quot;3600&quot;</span>);</span><br><span class="line">        response.setHeader(<span class="string">&quot;Access-Control-Allow-Headers&quot;</span>, <span class="string">&quot;Origin,Content-Type,Accept,token,X-Requested-With&quot;</span>);</span><br><span class="line">        chain.doFilter(req, res);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>JSON序列化配置，处理BigDecimal类型</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.jd.config;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.core.JsonGenerator;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.JsonSerializer;</span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.SerializerProvider;</span><br><span class="line"><span class="keyword">import</span> org.springframework.context.annotation.Configuration;</span><br><span class="line"><span class="keyword">import</span> java.io.IOException;</span><br><span class="line"><span class="keyword">import</span> java.math.BigDecimal;</span><br><span class="line"><span class="keyword">import</span> java.text.DecimalFormat;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@projectName</span>: jd-search-api</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@className</span>: com.jd.config.BigDecimalSerializer</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span>: BigDecimal序列化设置</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: tong.li</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@createTime</span>: 2020/12/10 20:16</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span>: v1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@copyright</span>: 版权所有 © 李彤</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Configuration</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">BigDecimalSerializer</span> <span class="keyword">extends</span> <span class="title class_">JsonSerializer</span>&lt;BigDecimal&gt; &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">void</span> <span class="title function_">serialize</span><span class="params">(BigDecimal value, JsonGenerator gen, SerializerProvider serializers)</span> <span class="keyword">throws</span> IOException &#123;</span><br><span class="line">        <span class="keyword">if</span> (value == <span class="literal">null</span> || value.compareTo(BigDecimal.ZERO) == <span class="number">0</span>) &#123;</span><br><span class="line">            gen.writeString(<span class="string">&quot;0.00&quot;</span>);</span><br><span class="line">            <span class="keyword">return</span>;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="type">DecimalFormat</span> <span class="variable">df</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">DecimalFormat</span>(<span class="string">&quot;#.00&quot;</span>);</span><br><span class="line">        gen.writeString(df.format(value));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>实体定义</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.jd.entity;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.annotation.JsonSerialize;</span><br><span class="line"><span class="keyword">import</span> com.jd.config.BigDecimalSerializer;</span><br><span class="line"><span class="keyword">import</span> lombok.Data;</span><br><span class="line"><span class="keyword">import</span> java.io.Serializable;</span><br><span class="line"><span class="keyword">import</span> java.math.BigDecimal;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@projectName</span>: jd-search-apihlightBuilder;</span></span><br><span class="line"><span class="comment">import org.elasticsearch.search.fetch.subphase.highlight.Hig</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@className</span>: com.jd.entity.GoodsDetail</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span>: 商品详情实体类</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: tong.li</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@createTime</span>: 2020/12/8 19:14</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span>: v1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@copyright</span>: 版权所有 © 李彤</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Data</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">GoodsDetail</span> <span class="keyword">implements</span> <span class="title class_">Serializable</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">long</span> <span class="variable">serialVersionUID</span> <span class="operator">=</span> <span class="number">121384327857834L</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 商品ID</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Long id;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 商品SKU标识</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String sku;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 商品名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String title;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 商品图片</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String imgUrl;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 商品价格</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@JsonSerialize(using = BigDecimalSerializer.class)</span></span><br><span class="line">    <span class="keyword">private</span> BigDecimal price;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 商品所在的商户名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String shopName;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 评价数</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Integer evaluationCount;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 成交数，随机生成</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> Integer transactionsCount;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 商品详情页跳转地址</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> String detailUrl;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 搜索排名</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="type">float</span> score;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
</ul>
<ul>
<li><p>web表现层：Controller定义接口</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.jd.controller;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.jd.service.ISearchService;</span><br><span class="line"><span class="keyword">import</span> lombok.extern.slf4j.Slf4j;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.GetMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestMapping;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RequestParam;</span><br><span class="line"><span class="keyword">import</span> org.springframework.web.bind.annotation.RestController;</span><br><span class="line"><span class="keyword">import</span> java.time.LocalDateTime;</span><br><span class="line"><span class="keyword">import</span> java.util.LinkedHashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@projectName</span>: jd-search-api</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@className</span>: com.jd.controller.SearchController</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span>: 搜索相关接口</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: tong.li</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@createTime</span>: 2020/12/8 19:21</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span>: v1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@copyright</span>: 版权所有 © 李彤</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@RestController</span></span><br><span class="line"><span class="meta">@RequestMapping(&quot;/jd&quot;)</span></span><br><span class="line"><span class="meta">@Slf4j</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SearchController</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> ISearchService searchService;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 搜索API GET请求</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> keywords   搜索关键字</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> pageNo     分页页码,不传默认查第一页</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> pageSize   分页页大小,不传默认查一页查30条</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> sortNumber 排序号(排序字段) 0-按默认评分排序,1-按评价数排序,2-按价格排序</span></span><br><span class="line"><span class="comment">     * <span class="doctag">@param</span> isDesc     是否倒叙排序,默认倒序</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@GetMapping(&quot;/search&quot;)</span></span><br><span class="line">    <span class="keyword">public</span> Map&lt;String, Object&gt; <span class="title function_">searchGoods</span><span class="params">(<span class="meta">@RequestParam(required = false)</span> String keywords,</span></span><br><span class="line"><span class="params">                                <span class="meta">@RequestParam(required = false, defaultValue = &quot;1&quot;)</span> Integer pageNo,</span></span><br><span class="line"><span class="params">                                <span class="meta">@RequestParam(required = false, defaultValue = &quot;30&quot;)</span> Integer pageSize,</span></span><br><span class="line"><span class="params">                                <span class="meta">@RequestParam(required = false, defaultValue = &quot;0&quot;)</span> Integer sortNumber,</span></span><br><span class="line"><span class="params">                                <span class="meta">@RequestParam(required = false, defaultValue = &quot;true&quot;)</span> Boolean isDesc)</span> &#123;</span><br><span class="line">          log.info(<span class="string">&quot;搜索参数:&#123;&#125;,&#123;&#125;,&#123;&#125;,&#123;&#125;,&#123;&#125;&quot;</span>,keywords, pageNo, pageSize, sortNumber, isDesc);</span><br><span class="line">        <span class="comment">// 为了程序严谨性,处理一下页码和页大小</span></span><br><span class="line">        pageNo = pageNo &lt;= <span class="number">0</span> ? <span class="number">1</span> : pageNo;</span><br><span class="line">        pageSize = pageSize &lt;= <span class="number">0</span> ? <span class="number">30</span> : pageSize;</span><br><span class="line">        <span class="comment">// 进行条件搜索</span></span><br><span class="line">        Map&lt;String, Object&gt; rs = <span class="keyword">new</span> <span class="title class_">LinkedHashMap</span>&lt;&gt;();</span><br><span class="line">        rs.put(<span class="string">&quot;timestamp&quot;</span>, LocalDateTime.now());</span><br><span class="line">        <span class="keyword">try</span> &#123;</span><br><span class="line">            <span class="comment">// 这里为了方便模拟真实项目开发，使用Map组装返回给前端，实际开发中是封装的泛型响应实体类为主</span></span><br><span class="line">            rs.put(<span class="string">&quot;status&quot;</span>, <span class="number">200</span>);</span><br><span class="line">            rs.put(<span class="string">&quot;message&quot;</span>, <span class="string">&quot;搜索成功&quot;</span>);</span><br><span class="line">            rs.put(<span class="string">&quot;data&quot;</span>,searchService.search(keywords, pageNo, pageSize,sortNumber,isDesc));</span><br><span class="line">        &#125; <span class="keyword">catch</span> (Exception e) &#123;</span><br><span class="line">            rs.put(<span class="string">&quot;status&quot;</span>, <span class="number">500</span>);</span><br><span class="line">            rs.put(<span class="string">&quot;message&quot;</span>, <span class="string">&quot;搜索失败,服务器异常&quot;</span>);</span><br><span class="line">            rs.put(<span class="string">&quot;data&quot;</span>,<span class="literal">null</span>);</span><br><span class="line">            log.error(<span class="string">&quot;搜索异常&quot;</span>, e);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">return</span> rs;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>业务处理层：Service处理搜索逻辑</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@projectName</span>: jd-search-api</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@className</span>: com.jd.service.impl.ISearchService</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span>: 搜索API接口抽象层</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: tong.li</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@createTime</span>: 2020/12/8 19:41</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span>: v1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@copyright</span>: 版权所有 © 李彤</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">interface</span> <span class="title class_">ISearchService</span> &#123;</span><br><span class="line"></span><br><span class="line">    PageInfo <span class="title function_">search</span><span class="params">(String keywords, Integer pageNo, Integer pageSize,Integer sortNumber,  Boolean isDesc)</span> <span class="keyword">throws</span> Exception;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.jd.service.impl;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> com.fasterxml.jackson.databind.ObjectMapper;</span><br><span class="line"><span class="keyword">import</span> com.github.pagehelper.PageInfo;</span><br><span class="line"><span class="keyword">import</span> com.jd.entity.GoodsDetail;</span><br><span class="line"><span class="keyword">import</span> com.jd.service.ISearchService;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.search.SearchRequest;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.action.search.SearchResponse;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.RequestOptions;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.client.RestHighLevelClient;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.common.text.Text;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.common.unit.TimeValue;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.index.query.MatchQueryBuilder;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.index.query.QueryBuilders;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.SearchHit;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.SearchHits;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.builder.SearchSourceBuilder;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.fetch.subphase.highlight.HighlightField;</span><br><span class="line"><span class="keyword">import</span> org.elasticsearch.search.sort.SortOrder;</span><br><span class="line"><span class="keyword">import</span> org.springframework.beans.factory.annotation.Autowired;</span><br><span class="line"><span class="keyword">import</span> org.springframework.stereotype.Service;</span><br><span class="line"><span class="keyword">import</span> org.springframework.util.CollectionUtils;</span><br><span class="line"><span class="keyword">import</span> org.springframework.util.ObjectUtils;</span><br><span class="line"><span class="keyword">import</span> java.util.ArrayList;</span><br><span class="line"><span class="keyword">import</span> java.util.HashMap;</span><br><span class="line"><span class="keyword">import</span> java.util.List;</span><br><span class="line"><span class="keyword">import</span> java.util.Map;</span><br><span class="line"><span class="keyword">import</span> java.util.concurrent.TimeUnit;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@projectName</span>: jd-search-api</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@className</span>: com.jd.service.impl.SearchServiceImpl</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@description</span>: 搜索实现逻辑层</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span>: tong.li</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@createTime</span>: 2020/12/8 1:942</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span>: v1.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@copyright</span>: 版权所有 © 李彤</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@Service</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">SearchServiceImpl</span> <span class="keyword">implements</span> <span class="title class_">ISearchService</span>  &#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 京东商品数据索引名称</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">JD_GOODS_INDEX_NAME</span> <span class="operator">=</span> <span class="string">&quot;jd_goods&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * title字段名</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> <span class="keyword">final</span> <span class="type">String</span> <span class="variable">FILED_NAME_TITLE</span> <span class="operator">=</span> <span class="string">&quot;title&quot;</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Jackson序列化</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> ObjectMapper objectMapper;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">private</span> <span class="keyword">static</span> Map&lt;Integer, String&gt; sortFiledMap;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">static</span> &#123;</span><br><span class="line">        sortFiledMap = <span class="keyword">new</span> <span class="title class_">HashMap</span>&lt;Integer, String&gt;() &#123;</span><br><span class="line">            &#123;</span><br><span class="line">                <span class="comment">// 人气按评价数排序</span></span><br><span class="line">                put(<span class="number">1</span>,<span class="string">&quot;evaluationCount&quot;</span>);</span><br><span class="line">                <span class="comment">// 按价格排序</span></span><br><span class="line">                put(<span class="number">2</span>,<span class="string">&quot;price&quot;</span>);</span><br><span class="line">            &#125;</span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * 官方建议使用ElasticSearch高级的Rest客户端</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="meta">@Autowired</span></span><br><span class="line">    <span class="keyword">private</span> RestHighLevelClient restHighLevelClient;</span><br><span class="line"></span><br><span class="line">    <span class="meta">@Override</span></span><br><span class="line">    <span class="keyword">public</span> PageInfo <span class="title function_">search</span><span class="params">(String keywords, Integer pageNo, Integer pageSize,Integer sortNumber, Boolean isDesc)</span> <span class="keyword">throws</span> Exception &#123;</span><br><span class="line">        <span class="comment">// 存放搜索后的数据</span></span><br><span class="line">        List&lt;GoodsDetail&gt; data = <span class="keyword">new</span> <span class="title class_">ArrayList</span>&lt;&gt;();</span><br><span class="line">        <span class="comment">// 构建搜索请求</span></span><br><span class="line">        <span class="type">SearchRequest</span> <span class="variable">searchRequest</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SearchRequest</span>(JD_GOODS_INDEX_NAME);</span><br><span class="line">        <span class="comment">// 构建SearchSourceBuilder方便查询</span></span><br><span class="line">        <span class="type">SearchSourceBuilder</span> <span class="variable">sourceBuilder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">SearchSourceBuilder</span>();</span><br><span class="line">        <span class="comment">// 分页设置，from是从哪个索引查，size是大小</span></span><br><span class="line">        sourceBuilder.from((pageNo-<span class="number">1</span>) * pageSize);</span><br><span class="line">        sourceBuilder.size(pageSize);</span><br><span class="line">        <span class="comment">// 设置排序，若sortNumber小于等于0，则是默认score排序，若大于1，则按指定字段排序</span></span><br><span class="line">        <span class="keyword">if</span> (sortNumber &gt; <span class="number">0</span> &amp;&amp; sortNumber &lt;= <span class="number">2</span>) &#123;</span><br><span class="line">            <span class="comment">// 这里需要注意，字段进行聚合和排序操作时，如果字段类型是Text类型的,会报错。</span></span><br><span class="line">            <span class="comment">// 由于ES默认情况下会禁用Text字段优化，因此无法进行聚合或排序。若想启用,请将字段的fielddata设置为true，通过取消反转索引来加载字段数据</span></span><br><span class="line">            <span class="comment">// 这种处理方法会占用大量内存,ES官方不建议这样做，建议更改要聚合或排序字段的字段类型</span></span><br><span class="line">            <span class="comment">// ES默认score排序,若使用其他字段排序,score是获取不到的</span></span><br><span class="line">            sourceBuilder.sort(sortFiledMap.get(sortNumber) ,isDesc ? SortOrder.DESC : SortOrder.ASC);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// 查询keywords</span></span><br><span class="line">        <span class="keyword">if</span> (!ObjectUtils.isEmpty(keywords)) &#123;</span><br><span class="line">            <span class="type">MatchQueryBuilder</span> <span class="variable">titleQueryBuilder</span> <span class="operator">=</span> QueryBuilders.matchQuery(FILED_NAME_TITLE, keywords);</span><br><span class="line">            sourceBuilder.query(titleQueryBuilder);</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 高亮设置</span></span><br><span class="line">        <span class="type">HighlightBuilder</span> <span class="variable">highlightBuilder</span> <span class="operator">=</span> <span class="keyword">new</span> <span class="title class_">HighlightBuilder</span>();</span><br><span class="line">        highlightBuilder.field(<span class="string">&quot;title&quot;</span>) <span class="comment">// 设置高亮字段</span></span><br><span class="line">                .preTags(<span class="string">&quot;&lt;span style=&#x27;color:red&#x27;&gt;&quot;</span>)      <span class="comment">// 设置前置标签以及样式</span></span><br><span class="line">                .postTags(<span class="string">&quot;&lt;/span&gt;&quot;</span>)    <span class="comment">// 设置闭合标签以及样式</span></span><br><span class="line">                .highlighterType(<span class="string">&quot;unified&quot;</span>) <span class="comment">// 设置高亮类型</span></span><br><span class="line">                .requireFieldMatch(<span class="literal">false</span>); <span class="comment">// 关闭多个字段高亮</span></span><br><span class="line">        sourceBuilder.highlighter(highlightBuilder);</span><br><span class="line">        <span class="comment">// 设置超时时间为60秒</span></span><br><span class="line">        sourceBuilder.timeout(<span class="keyword">new</span> <span class="title class_">TimeValue</span>(<span class="number">60</span>, TimeUnit.SECONDS));</span><br><span class="line">        <span class="comment">// 执行搜索</span></span><br><span class="line">        searchRequest.source(sourceBuilder);</span><br><span class="line">        <span class="type">SearchResponse</span> <span class="variable">searchResponse</span> <span class="operator">=</span> restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);</span><br><span class="line">        <span class="comment">// 获取结果</span></span><br><span class="line">        <span class="type">SearchHits</span> <span class="variable">hits</span> <span class="operator">=</span> searchResponse.getHits();</span><br><span class="line">        <span class="comment">// 创建分页对象</span></span><br><span class="line">        PageInfo&lt;GoodsDetail&gt; pageInfo = <span class="keyword">new</span> <span class="title class_">PageInfo</span>&lt;&gt;(data);</span><br><span class="line">        <span class="comment">// 设置分页数据</span></span><br><span class="line">        pageInfo.setPageNum(pageNo);</span><br><span class="line">        pageInfo.setPageSize(pageSize);</span><br><span class="line">        <span class="keyword">if</span> (hits == <span class="literal">null</span> || hits.getTotalHits().value == <span class="number">0</span>) &#123;</span><br><span class="line">            <span class="keyword">return</span> pageInfo;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 解析结果</span></span><br><span class="line">        <span class="keyword">for</span> (SearchHit hit : hits) &#123;</span><br><span class="line">            <span class="type">String</span> <span class="variable">sourceAsString</span> <span class="operator">=</span> hit.getSourceAsString();</span><br><span class="line">            <span class="type">GoodsDetail</span> <span class="variable">goodsDetail</span> <span class="operator">=</span> objectMapper.readValue(sourceAsString, GoodsDetail.class);</span><br><span class="line">            <span class="comment">// 获取高亮字段</span></span><br><span class="line">            Map&lt;String, HighlightField&gt; highlightFields = hit.getHighlightFields();</span><br><span class="line">            <span class="type">HighlightField</span> <span class="variable">title</span> <span class="operator">=</span> <span class="literal">null</span>;</span><br><span class="line">            <span class="keyword">if</span> (!CollectionUtils.isEmpty(highlightFields)) &#123;</span><br><span class="line">                title = highlightFields.get(FILED_NAME_TITLE);</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="keyword">if</span> (title != <span class="literal">null</span>) &#123;</span><br><span class="line">                <span class="comment">// 如果存在高亮字段，解析高亮字段并将原来的字段值覆盖掉</span></span><br><span class="line">                Text[] fragments = title.getFragments();</span><br><span class="line">                <span class="keyword">if</span> (fragments != <span class="literal">null</span> &amp;&amp; fragments.length &gt; <span class="number">0</span>) &#123;</span><br><span class="line">                    goodsDetail.setTitle(fragments[<span class="number">0</span>].string());</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="comment">// 设置排名</span></span><br><span class="line">            goodsDetail.setScore(Float.isNaN(hit.getScore()) ? <span class="number">0.0f</span> : hit.getScore());</span><br><span class="line">            data.add(goodsDetail);</span><br><span class="line"></span><br><span class="line">        &#125;</span><br><span class="line">        <span class="comment">// 获取总数</span></span><br><span class="line">        <span class="type">long</span> <span class="variable">total</span> <span class="operator">=</span> hits.getTotalHits().value;</span><br><span class="line">        pageInfo.setTotal(total);</span><br><span class="line">        pageInfo.setList(data);</span><br><span class="line">        <span class="comment">// 当前页的数量</span></span><br><span class="line">        pageInfo.setSize(data.size());</span><br><span class="line">        <span class="comment">// 总共多少页</span></span><br><span class="line">        pageInfo.setPages(total== <span class="number">0</span> ? <span class="number">0</span>: (<span class="type">int</span>) (total % pageSize == <span class="number">0</span> ? total / pageSize : (total / pageSize) + <span class="number">1</span>));</span><br><span class="line">        <span class="comment">// 是否有下一页</span></span><br><span class="line">        pageInfo.setHasNextPage(pageInfo.getPageNum() &lt; pageInfo.getPages());</span><br><span class="line">        <span class="comment">// 是否有上一页</span></span><br><span class="line">        pageInfo.setHasPreviousPage(pageInfo.getPageNum() &gt; <span class="number">1</span> &amp;&amp;  pageInfo.getPageNum() &lt;= pageInfo.getPages() );</span><br><span class="line">        <span class="comment">// 是否为第一页</span></span><br><span class="line">        pageInfo.setIsFirstPage(pageInfo.getPageNum() == <span class="number">1</span>);</span><br><span class="line">        <span class="comment">// 是否为最后一页</span></span><br><span class="line">        pageInfo.setIsLastPage(pageInfo.getPageNum() == pageInfo.getPages());</span><br><span class="line">        <span class="keyword">return</span> pageInfo;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>启动类</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">package</span> com.jd;</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.SpringApplication;</span><br><span class="line"><span class="keyword">import</span> org.springframework.boot.autoconfigure.SpringBootApplication;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 启动类，直接运行即可</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">@SpringBootApplication</span></span><br><span class="line"><span class="keyword">public</span> <span class="keyword">class</span> <span class="title class_">Application</span> &#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">public</span> <span class="keyword">static</span> <span class="keyword">void</span> <span class="title function_">main</span><span class="params">(String[] args)</span> &#123;</span><br><span class="line">        SpringApplication.run(Application.class, args);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>运行启用类成功后，测试接口，接口地址如下:</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">http://localhost:9000/jd/search?keywords=佳能&amp;pageNo=1&amp;pageSize=30&amp;sortNumber=2&amp;isDesc=<span class="literal">true</span> </span><br></pre></td></tr></table></figure>

<p><img src="https://ltyeamin.github.io/imgs/2020/12/20201211131207.png" alt="image-20201211131158776"></p>
</li>
</ul>
<h1 id="5-前后端对接"><a href="#5-前后端对接" class="headerlink" title="5. 前后端对接"></a>5. 前后端对接</h1><ul>
<li><p>前提条件:启动ElasticSearch服务保证数据可用、启动后端服务保证接口可用、前端安装Axios库、qs库、Element组件库</p>
</li>
<li><p>前端接口请求</p>
<figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> <span class="title class_">Vue</span> <span class="keyword">from</span> <span class="string">&#x27;vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> <span class="title class_">App</span> <span class="keyword">from</span> <span class="string">&#x27;./App.vue&#x27;</span></span><br><span class="line"><span class="keyword">import</span> router <span class="keyword">from</span> <span class="string">&#x27;./router&#x27;</span></span><br><span class="line"><span class="comment">// 导入CSS样式</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;./assets/css/style.css&#x27;</span></span><br><span class="line"><span class="comment">// 导入axios</span></span><br><span class="line"><span class="keyword">import</span> axios <span class="keyword">from</span> <span class="string">&#x27;axios&#x27;</span></span><br><span class="line"><span class="comment">// 导入qs用于url序列化</span></span><br><span class="line"><span class="keyword">import</span> qs <span class="keyword">from</span> <span class="string">&#x27;qs&#x27;</span></span><br><span class="line"><span class="comment">// 导入Element-Ui组件</span></span><br><span class="line"><span class="keyword">import</span> <span class="string">&#x27;./plugins/element.js&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 配置请求根目录</span></span><br><span class="line">axios.<span class="property">defaults</span>.<span class="property">baseURL</span> = <span class="string">&#x27;http://localhost:9000/jd&#x27;</span></span><br><span class="line"><span class="comment">// 给Vue挂载axios</span></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$http</span> = axios</span><br><span class="line"><span class="title class_">Vue</span>.<span class="property"><span class="keyword">prototype</span></span>.<span class="property">$qs</span> = qs</span><br><span class="line"></span><br><span class="line"><span class="title class_">Vue</span>.<span class="property">config</span>.<span class="property">productionTip</span> = <span class="literal">false</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">new</span> <span class="title class_">Vue</span>(&#123;</span><br><span class="line">  <span class="comment">// 通过mounted生命周期钩子初始化数据</span></span><br><span class="line">  <span class="attr">mounted</span>: <span class="keyword">async</span> <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="comment">// 初始化品牌数据</span></span><br><span class="line">    <span class="keyword">const</span> initBrandList = [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;佳能&#x27;</span></span><br><span class="line">      &#125;, &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">2</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;尼康&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">3</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;索尼&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">4</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;哈苏&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">5</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;富士&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">6</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;莱卡&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">7</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;松下&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">8</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;大疆&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">9</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;适马&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">10</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;松典&#x27;</span></span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">    <span class="comment">// 初始化排序数据</span></span><br><span class="line">    <span class="keyword">const</span> sortData = [</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">0</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;综合&#x27;</span>,</span><br><span class="line">        <span class="attr">defaultDesc</span>: <span class="string">&#x27;true&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">1</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;人气&#x27;</span>,</span><br><span class="line">        <span class="attr">defaultDesc</span>: <span class="string">&#x27;true&#x27;</span></span><br><span class="line">      &#125;,</span><br><span class="line">      &#123;</span><br><span class="line">        <span class="attr">id</span>: <span class="number">2</span>,</span><br><span class="line">        <span class="attr">name</span>: <span class="string">&#x27;价格&#x27;</span>,</span><br><span class="line">        <span class="attr">defaultDesc</span>: <span class="string">&#x27;false&#x27;</span></span><br><span class="line">      &#125;</span><br><span class="line">    ]</span><br><span class="line">    <span class="keyword">const</span> &#123; <span class="attr">data</span>: rs &#125; = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="property">$http</span>.<span class="title function_">get</span>(<span class="string">&#x27;/search?&#x27;</span> + <span class="variable language_">this</span>.<span class="property">$qs</span>.<span class="title function_">stringify</span>(<span class="variable language_">this</span>.<span class="property">params</span>))</span><br><span class="line">    <span class="keyword">if</span> (rs.<span class="property">status</span> !== <span class="number">200</span>) &#123;</span><br><span class="line">      <span class="comment">// 如果请求失败，进行弹框</span></span><br><span class="line">      <span class="keyword">return</span> <span class="variable language_">this</span>.$message(rs.<span class="property">message</span>)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 注释掉假数据，将查询的数据填充到该字段  </span></span><br><span class="line">    <span class="keyword">const</span> initGoodsData = rs.<span class="property">data</span></span><br><span class="line">  </span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(<span class="string">&#x27;initGoodsData&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(initGoodsData))</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(<span class="string">&#x27;initBrandList&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(initBrandList))</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">setItem</span>(<span class="string">&#x27;sortData&#x27;</span>, <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(sortData))</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 通过mounted生命周期钩子清除初始化数据</span></span><br><span class="line">  <span class="attr">destroyed</span>: <span class="keyword">function</span> (<span class="params"></span>) &#123;</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">removeItem</span>(<span class="string">&#x27;initGoodsData&#x27;</span>)</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">removeItem</span>(<span class="string">&#x27;brandList&#x27;</span>)</span><br><span class="line">    <span class="variable language_">localStorage</span>.<span class="title function_">removeItem</span>(<span class="string">&#x27;sortData&#x27;</span>)</span><br><span class="line">  &#125;,</span><br><span class="line">  router,</span><br><span class="line">  <span class="attr">render</span>: <span class="function"><span class="params">h</span> =&gt;</span> <span class="title function_">h</span>(<span class="title class_">App</span>)</span><br><span class="line">&#125;).$mount(<span class="string">&#x27;#app&#x27;</span>)</span><br></pre></td></tr></table></figure>

<figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">template</span>&gt;</span></span><br><span class="line">  <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;page&quot;</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;mallPage&quot;</span> <span class="attr">class</span>=<span class="string">&quot; mallist tmall- page-not-market &quot;</span>&gt;</span></span><br><span class="line">        <span class="comment">&lt;!-- 头部搜索 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;header&quot;</span> <span class="attr">class</span>=<span class="string">&quot; header-list-app&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;headerLayout&quot;</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;headerCon &quot;</span>&gt;</span></span><br><span class="line">                    <span class="comment">&lt;!-- Logo--&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">h1</span> <span class="attr">id</span>=<span class="string">&quot;mallLogo&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">img</span> <span class="attr">th:src</span>=<span class="string">&quot;../static/images/jdlogo.png&quot;</span> <span class="attr">alt</span>=<span class="string">&quot;&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">h1</span>&gt;</span></span><br><span class="line"></span><br><span class="line">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;header-extra&quot;</span>&gt;</span></span><br><span class="line"></span><br><span class="line">                        <span class="comment">&lt;!--搜索--&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;mallSearch&quot;</span> <span class="attr">class</span>=<span class="string">&quot;mall-search&quot;</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">form</span> <span class="attr">name</span>=<span class="string">&quot;searchTop&quot;</span> <span class="attr">class</span>=<span class="string">&quot;mallSearch-form clearfix&quot;</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">fieldset</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">legend</span>&gt;</span>天猫搜索<span class="tag">&lt;/<span class="name">legend</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;mallSearch-input clearfix&quot;</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;s-combobox&quot;</span> <span class="attr">id</span>=<span class="string">&quot;s-combobox-685&quot;</span>&gt;</span></span><br><span class="line">                                            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;s-combobox-input-wrap&quot;</span>&gt;</span></span><br><span class="line">                                                <span class="tag">&lt;<span class="name">input</span> <span class="attr">type</span>=<span class="string">&quot;text&quot;</span> <span class="attr">autocomplete</span>=<span class="string">&quot;off&quot;</span> <span class="attr">v-model</span>=<span class="string">&quot;params.keywords&quot;</span> <span class="attr">id</span>=<span class="string">&quot;mq&quot;</span></span></span><br><span class="line"><span class="tag">                                                       <span class="attr">class</span>=<span class="string">&quot;s-combobox-input&quot;</span> <span class="attr">aria-haspopup</span>=<span class="string">&quot;true&quot;</span> <span class="attr">placeholder</span>=<span class="string">&quot;请输入关键字&quot;</span>&gt;</span></span><br><span class="line">                                            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;<span class="name">button</span> <span class="attr">type</span>=<span class="string">&quot;submit&quot;</span> <span class="attr">id</span>=<span class="string">&quot;searchbtn&quot;</span>  @<span class="attr">click.prevent</span>=<span class="string">&quot;doSearch(params.keywords)&quot;</span>&gt;</span>搜索<span class="tag">&lt;/<span class="name">button</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">fieldset</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;relKeyTop&quot;</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥相机专场<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥聊Java<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥摄影大讲堂<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥电脑修理铺<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">li</span>&gt;</span><span class="tag">&lt;<span class="name">a</span>&gt;</span>彤哥图书<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">&lt;!-- 商品详情页面 --&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">id</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;main&quot;</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!-- 品牌分类 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">form</span> <span class="attr">class</span>=<span class="string">&quot;navAttrsForm&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;attrs j_NavAttrs&quot;</span> <span class="attr">style</span>=<span class="string">&quot;display:block&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;brandAttr j_nav_brand&quot;</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;j_Brand attr&quot;</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;attrKey&quot;</span>&gt;</span></span><br><span class="line">                                    你可能要搜</span><br><span class="line">                                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;attrValues&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">ul</span> <span class="attr">class</span>=<span class="string">&quot;av-collapse row-2&quot;</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;<span class="name">li</span> <span class="attr">v-for</span>=<span class="string">&quot;brand in brandList&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;brand.id&quot;</span> @<span class="attr">click.prevent</span>=<span class="string">&quot;doSearch(brand.name)&quot;</span>&gt;</span></span><br><span class="line">                                            <span class="tag">&lt;<span class="name">a</span> <span class="attr">href</span>=<span class="string">&quot;#&quot;</span>&gt;</span>&#123;&#123;brand.name&#125;&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;/<span class="name">li</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;/<span class="name">ul</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">form</span>&gt;</span></span><br><span class="line"></span><br><span class="line">                <span class="comment">&lt;!-- 排序规则 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;filter clearfix&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-for</span>=<span class="string">&quot;sortItem in sortData&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;sortItem.id&quot;</span> @<span class="attr">click</span>=<span class="string">&quot;doSortSearch(sortItem.id,sortItem.defaultDesc)&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;fSort&quot;</span> <span class="attr">:class</span>=<span class="string">&quot;&#123;&#x27;fSort-cur&#x27;: sortItem.id == defaultSortNumber&#125;&quot;</span>&gt;</span></span><br><span class="line">                        &#123;&#123;sortItem.name&#125;&#125;</span><br><span class="line">                        <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-if</span>=<span class="string">&quot;sortItem.id &gt; 1&quot;</span>&gt;</span></span><br><span class="line">                            <span class="comment">&lt;!-- 排序上标志，阻止向父级冒泡 --&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;f-ico-triangle-mt&quot;</span> <span class="attr">:style</span>=<span class="string">&quot;sortViewFlag==1 ? &#123;&#x27;border-bottom&#x27;: &#x27;4px solid red&#x27;&#125; : &#123;&#125;&quot;</span> @<span class="attr">click.stop</span>=<span class="string">&quot;doSortSearch(sortItem.id,false)&quot;</span> &gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">                            <span class="comment">&lt;!-- 排序下标志，阻止向父级冒泡 --&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;f-ico-triangle-mb&quot;</span> <span class="attr">:style</span>=<span class="string">&quot;sortViewFlag==2 ? &#123;&#x27;border-top&#x27;: &#x27;4px solid red&#x27;&#125; : &#123;&#125;&quot;</span>  @<span class="attr">click.stop</span>=<span class="string">&quot;doSortSearch(sortItem.id,true)&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">span</span> <span class="attr">v-else</span>&gt;</span></span><br><span class="line">                           <span class="tag">&lt;<span class="name">i</span> <span class="attr">class</span>=<span class="string">&quot;f-ico-arrow-d&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">i</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="comment">&lt;!-- 商品详情，滚动加载 --&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;view grid-nosku&quot;</span> <span class="attr">infinite-scroll-disabled</span>=<span class="string">&quot;disabled&quot;</span> <span class="attr">v-infinite-scroll</span>=<span class="string">&quot;loadMore&quot;</span> <span class="attr">v-if</span>=<span class="string">&quot;jdGoodsList !== null &amp;&amp; &#x27;list&#x27; in jdGoodsList &amp;&amp; jdGoodsList !== null&quot;</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;product&quot;</span>  <span class="attr">v-for</span>=<span class="string">&quot;goods in jdGoodsList.list&quot;</span> <span class="attr">:key</span>=<span class="string">&quot;goods.id&quot;</span>&gt;</span></span><br><span class="line">                        <span class="tag">&lt;<span class="name">a</span> <span class="attr">:href</span>=<span class="string">&quot;goods.detailUrl&quot;</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;product-iWrap&quot;</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!--商品封面--&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;productImg-wrap&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">a</span> <span class="attr">class</span>=<span class="string">&quot;productImg&quot;</span>&gt;</span></span><br><span class="line">                                        <span class="tag">&lt;<span class="name">img</span> <span class="attr">:src</span>=<span class="string">&quot;goods.imgUrl&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!--价格--&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;productPrice&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">em</span>&gt;</span><span class="tag">&lt;<span class="name">b</span>&gt;</span>¥<span class="tag">&lt;/<span class="name">b</span>&gt;</span>&#123;&#123;goods.price&#125;&#125;<span class="tag">&lt;/<span class="name">em</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!--标题--&gt;</span>xiaog</span><br><span class="line">                                <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;productTitle&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="comment">&lt;!-- 使用v-html原因是高亮渲染 --&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">a</span>  <span class="attr">v-html</span>=<span class="string">&quot;goods.title&quot;</span>&gt;</span><span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!-- 店铺名 --&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;productShop&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">span</span>&gt;</span>店铺：&#123;&#123;goods.shopName&#125;&#125; <span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                                <span class="comment">&lt;!-- 成交信息 --&gt;</span></span><br><span class="line">                                <span class="tag">&lt;<span class="name">p</span> <span class="attr">class</span>=<span class="string">&quot;productStatus&quot;</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">span</span>&gt;</span>月成交<span class="tag">&lt;<span class="name">em</span>&gt;</span>&#123;&#123;goods.transactionsCount&#125;&#125;笔<span class="tag">&lt;/<span class="name">em</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                                    <span class="tag">&lt;<span class="name">span</span>&gt;</span>评价 <span class="tag">&lt;<span class="name">a</span>&gt;</span>&#123;&#123;goods.evaluationCount&#125;&#125;<span class="tag">&lt;/<span class="name">a</span>&gt;</span><span class="tag">&lt;/<span class="name">span</span>&gt;</span></span><br><span class="line">                                <span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">                            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                         <span class="tag">&lt;/<span class="name">a</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;<span class="name">div</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">p</span> <span class="attr">v-if</span>=<span class="string">&quot;this.loading&quot;</span>&gt;</span>加载中...<span class="tag">&lt;/<span class="name">p</span>&gt;</span></span><br><span class="line">                    <span class="tag">&lt;<span class="name">div</span>&gt;</span><span class="tag">&lt;<span class="name">p</span> <span class="attr">v-if</span>=<span class="string">&quot;this.noMore&quot;</span>&gt;</span>没有更多了<span class="tag">&lt;/<span class="name">p</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">                <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">            <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="comment">&lt;!-- 回到顶部 --&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">el-backtop</span> <span class="attr">target</span>=<span class="string">&quot;#mallPage&quot;</span> <span class="attr">:bottom</span>=<span class="string">&quot;100&quot;</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;back-top&quot;</span> &gt;</span>UP<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">el-backtop</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">template</span>&gt;</span></span><br><span class="line"></span><br><span class="line"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="language-javascript"></span></span><br><span class="line"><span class="language-javascript"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">name</span>: <span class="string">&#x27;Search&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">  data () &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">return</span> &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">sortData</span>: <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;sortData&#x27;</span>)),</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">brandList</span>: <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;initBrandList&#x27;</span>)),</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">params</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">keywords</span>: <span class="string">&#x27;&#x27;</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">pageNo</span>: <span class="number">1</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">pageSize</span>: <span class="number">30</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">sortNumber</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">        <span class="attr">isDesc</span>: <span class="literal">true</span></span></span><br><span class="line"><span class="language-javascript">      &#125;,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">jdGoodsList</span>: <span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="variable language_">localStorage</span>.<span class="title function_">getItem</span>(<span class="string">&#x27;initGoodsData&#x27;</span>)),</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">defaultSortNumber</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">sortViewFlag</span>: <span class="number">0</span>,</span></span><br><span class="line"><span class="language-javascript">      <span class="attr">loading</span>: <span class="literal">false</span></span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;,</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">props</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">  &#125;,</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">methods</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">async</span> doSearch (keywords, sc) &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="keyword">typeof</span> (sc) === <span class="string">&#x27;undefined&#x27;</span>)</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (<span class="keyword">typeof</span> (sc) === <span class="string">&#x27;undefined&#x27;</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">pageNo</span> = <span class="number">1</span></span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">keywords</span> = keywords</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 请求后端接口进行搜索操作</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">const</span> &#123; <span class="attr">data</span>: rs &#125; = <span class="keyword">await</span> <span class="variable language_">this</span>.<span class="property">$http</span>.<span class="title function_">get</span>(<span class="string">&#x27;/search?&#x27;</span> + <span class="variable language_">this</span>.<span class="property">$qs</span>.<span class="title function_">stringify</span>(<span class="variable language_">this</span>.<span class="property">params</span>))</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (rs.<span class="property">status</span> !== <span class="number">200</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 如果请求失败，进行弹框</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">$message</span>.<span class="title function_">error</span>(rs.<span class="property">message</span>)</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (sc === <span class="literal">true</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="property">jdGoodsList</span>.<span class="property">list</span> = <span class="variable language_">this</span>.<span class="property">jdGoodsList</span>.<span class="property">list</span>.<span class="title function_">concat</span>(rs.<span class="property">data</span>.<span class="property">list</span>)</span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">return</span></span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">jdGoodsList</span> = rs.<span class="property">data</span></span></span><br><span class="line"><span class="language-javascript">    &#125;,</span></span><br><span class="line"><span class="language-javascript">    <span class="keyword">async</span> doSortSearch (id, defaultDesc) &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 排序字段置为选中</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (id === <span class="number">2</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 排序箭头置为选中</span></span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="property">sortViewFlag</span> = !defaultDesc ? <span class="number">1</span> : <span class="number">2</span></span></span><br><span class="line"><span class="language-javascript">        defaultDesc = (<span class="variable language_">this</span>.<span class="property">sortViewFlag</span> === <span class="number">2</span>)</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">defaultSortNumber</span> = id</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 重新设置排序号和排序规则</span></span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">sortNumber</span> = id</span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">isDesc</span> = defaultDesc</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 执行搜索</span></span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="title function_">doSearch</span>(<span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">keywords</span>)</span></span><br><span class="line"><span class="language-javascript">    &#125;,</span></span><br><span class="line"><span class="language-javascript">    <span class="comment">/**</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">     * 滚动加载</span></span></span><br><span class="line"><span class="comment"><span class="language-javascript">     */</span></span></span><br><span class="line"><span class="language-javascript">    loadMore () &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="variable language_">this</span>.<span class="property">loading</span> = <span class="literal">true</span></span></span><br><span class="line"><span class="language-javascript">      <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 页码+1</span></span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">pageNo</span> += <span class="number">1</span></span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="property">loading</span> = <span class="literal">false</span></span></span><br><span class="line"><span class="language-javascript">        <span class="keyword">if</span> (<span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">pageNo</span> &gt; <span class="variable language_">this</span>.<span class="property">jdGoodsList</span>.<span class="property">pages</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">          <span class="comment">// 加载完成所有数据后，将页码置为初始值1</span></span></span><br><span class="line"><span class="language-javascript">          <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">pageNo</span> = <span class="number">1</span></span></span><br><span class="line"><span class="language-javascript">          <span class="keyword">return</span></span></span><br><span class="line"><span class="language-javascript">        &#125;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 执行搜索</span></span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="title function_">doSearch</span>(<span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">keywords</span>, <span class="literal">true</span>)</span></span><br><span class="line"><span class="language-javascript">      &#125;, <span class="number">2000</span>)</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;,</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">watch</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">    <span class="string">&#x27;params.keywords&#x27;</span>: <span class="keyword">async</span> <span class="keyword">function</span> (<span class="params">newVal</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="comment">// 若不搜索，则默认显示LocalStorage存储的商品信息</span></span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">if</span> (newVal === <span class="string">&#x27;&#x27;</span>) &#123;</span></span><br><span class="line"><span class="language-javascript">        <span class="comment">// 执行搜索</span></span></span><br><span class="line"><span class="language-javascript">        <span class="variable language_">this</span>.<span class="title function_">doSearch</span>(newVal)</span></span><br><span class="line"><span class="language-javascript">      &#125;</span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;,</span></span><br><span class="line"><span class="language-javascript">  <span class="attr">computed</span>: &#123;</span></span><br><span class="line"><span class="language-javascript">    noMore () &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">params</span>.<span class="property">pageNo</span> === <span class="variable language_">this</span>.<span class="property">jdGoodsList</span>.<span class="property">pages</span></span></span><br><span class="line"><span class="language-javascript">    &#125;,</span></span><br><span class="line"><span class="language-javascript">    disabled () &#123;</span></span><br><span class="line"><span class="language-javascript">      <span class="keyword">return</span> <span class="variable language_">this</span>.<span class="property">loading</span> || <span class="variable language_">this</span>.<span class="property">noMore</span></span></span><br><span class="line"><span class="language-javascript">    &#125;</span></span><br><span class="line"><span class="language-javascript">  &#125;</span></span><br><span class="line"><span class="language-javascript">&#125;</span></span><br><span class="line"><span class="language-javascript"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">style</span> <span class="attr">lang</span>=<span class="string">&quot;scss&quot;</span> <span class="attr">scope</span>&gt;</span><span class="language-css"></span></span><br><span class="line"><span class="language-css"><span class="selector-id">#mallPage</span> &#123;</span></span><br><span class="line"><span class="language-css">    <span class="attribute">height</span>: <span class="number">100vh</span>;</span></span><br><span class="line"><span class="language-css">    <span class="attribute">overflow-x</span>: hidden;</span></span><br><span class="line"><span class="language-css">&#125;</span></span><br><span class="line"><span class="language-css"><span class="selector-class">.back-top</span> &#123;</span></span><br><span class="line"><span class="language-css">    <span class="attribute">height</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">    <span class="attribute">width</span>: <span class="number">100%</span>;</span></span><br><span class="line"><span class="language-css">    <span class="attribute">background-color</span>: <span class="number">#f2f5f6</span>;</span></span><br><span class="line"><span class="language-css">    <span class="attribute">box-shadow</span>: <span class="number">0</span> <span class="number">0</span> <span class="number">6px</span> <span class="built_in">rgba</span>(<span class="number">0</span>,<span class="number">0</span>,<span class="number">0</span>, .<span class="number">12</span>);</span></span><br><span class="line"><span class="language-css">    <span class="attribute">text-align</span>: center;</span></span><br><span class="line"><span class="language-css">    <span class="attribute">line-height</span>: <span class="number">40px</span>;</span></span><br><span class="line"><span class="language-css">    <span class="attribute">color</span>: <span class="number">#1989fa</span>;</span></span><br><span class="line"><span class="language-css">&#125;</span></span><br><span class="line"><span class="language-css"></span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br></pre></td></tr></table></figure></li>
</ul>
<h1 id="6-最终效果"><a href="#6-最终效果" class="headerlink" title="6. 最终效果"></a>6. 最终效果</h1><p><img src="https://i.loli.net/2020/12/13/yqpx1UerO8MEl4n.gif" alt="最终效果"></p>
<h1 id="7-源码仓库"><a href="#7-源码仓库" class="headerlink" title="7. 源码仓库"></a>7. 源码仓库</h1><ul>
<li><a target="_blank" rel="noopener" href="https://gitee.com/ltalex/es-jd-search">码云</a></li>
</ul>
<h1 id="8-参考资料"><a href="#8-参考资料" class="headerlink" title="8. 参考资料"></a>8. 参考资料</h1><ul>
<li><a target="_blank" rel="noopener" href="https://www.elastic.co/cn/elasticsearch/">ElasticSearch官网</a></li>
<li><a target="_blank" rel="noopener" href="https://github.com/medcl/elasticsearch-analysis-ik">IK中文分词器</a></li>
<li><a target="_blank" rel="noopener" href="https://cn.vuejs.org/">Vue官网</a></li>
<li><a target="_blank" rel="noopener" href="https://element.eleme.cn/#/zh-CN/component/installation">Element-UI组件</a></li>
</ul>
</section>
    <!-- Tags START -->
    
      <div class="tags">
        <span>Tags:</span>
        
  <a href="/tags#Elastic Stack" >
    <span class="tag-code">Elastic Stack</span>
  </a>

      </div>
    
    <!-- Tags END -->
    <!-- NAV START -->
    
  <div class="nav-container">
    <!-- reverse left and right to put prev and next in a more logic postition -->
    
      <a class="nav-left" href="/2020/08/01/%E3%80%90%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E3%80%91%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95%E5%88%9D%E8%AF%86/">
        <span class="nav-arrow">← </span>
        
          【数据结构与算法】数据结构与算法初识
        
      </a>
    
    
      <a class="nav-right" href="/2021/05/24/Netty%E4%B8%93%E9%A2%98-%E5%88%9D%E8%AF%86NIO/">
        
          Netty专题-初识NIO
        
        <span class="nav-arrow"> →</span>
      </a>
    
  </div>

    <!-- NAV END -->
    <!-- 打赏 START -->
    
      <div class="money-like">
        <div class="reward-btn">
          赏
          <span class="money-code">
            <span class="alipay-code">
              <div class="code-image"></div>
              <b>使用支付宝打赏</b>
            </span>
            <span class="wechat-code">
              <div class="code-image"></div>
              <b>使用微信打赏</b>
            </span>
          </span>
        </div>
        <p class="notice">若你觉得我的文章对你有帮助，欢迎点击上方按钮对我打赏</p>
      </div>
    
    <!-- 打赏 END -->
    <!-- 二维码 START -->
    
      <div class="qrcode">
        <canvas id="share-qrcode"></canvas>
        <p class="notice">扫描二维码，分享此文章</p>
      </div>
    
    <!-- 二维码 END -->
    
      <!-- Utterances START -->
      <div id="utterances"></div>
      <script src="https://utteranc.es/client.js"
        repo="ltyeamin/blogtalks"
        issue-term="pathname"
        theme="github-light"
        crossorigin="anonymous"
        async></script>    
      <!-- Utterances END -->
    
  </article>
  <!-- Article END -->
  <!-- Catalog START -->
  
    <aside class="catalog-container">
  <div class="toc-main">
    <strong class="toc-title">Catalog</strong>
    
      <ol class="toc-nav"><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#1-%E5%89%8D%E8%A8%80"><span class="toc-nav-text">1. 前言</span></a></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#2-%E5%89%8D%E7%AB%AF%E9%A1%B5%E9%9D%A2%E5%87%86%E5%A4%87"><span class="toc-nav-text">2. 前端页面准备</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#2-1-%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87"><span class="toc-nav-text">2.1 环境准备</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#2-2-%E6%90%AD%E5%BB%BA%E9%A1%B9%E7%9B%AE"><span class="toc-nav-text">2.2 搭建项目</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#2-3-%E9%A1%B5%E9%9D%A2%E5%BC%80%E5%8F%91"><span class="toc-nav-text">2.3 页面开发</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#3-%E4%BA%AC%E4%B8%9C%E6%95%B0%E6%8D%AE%E7%88%AC%E5%8F%96"><span class="toc-nav-text">3. 京东数据爬取</span></a></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#4-%E5%90%8E%E7%AB%AF%E6%8E%A5%E5%8F%A3%E5%BC%80%E5%8F%91"><span class="toc-nav-text">4. 后端接口开发</span></a><ol class="toc-nav-child"><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#4-1-%E7%8E%AF%E5%A2%83%E5%87%86%E5%A4%87"><span class="toc-nav-text">4.1 环境准备</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#4-2-%E9%A1%B9%E7%9B%AE%E6%90%AD%E5%BB%BA"><span class="toc-nav-text">4.2 项目搭建</span></a></li><li class="toc-nav-item toc-nav-level-2"><a class="toc-nav-link" href="#4-3-%E6%8E%A5%E5%8F%A3%E5%BC%80%E5%8F%91"><span class="toc-nav-text">4.3 接口开发</span></a></li></ol></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#5-%E5%89%8D%E5%90%8E%E7%AB%AF%E5%AF%B9%E6%8E%A5"><span class="toc-nav-text">5. 前后端对接</span></a></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#6-%E6%9C%80%E7%BB%88%E6%95%88%E6%9E%9C"><span class="toc-nav-text">6. 最终效果</span></a></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#7-%E6%BA%90%E7%A0%81%E4%BB%93%E5%BA%93"><span class="toc-nav-text">7. 源码仓库</span></a></li><li class="toc-nav-item toc-nav-level-1"><a class="toc-nav-link" href="#8-%E5%8F%82%E8%80%83%E8%B5%84%E6%96%99"><span class="toc-nav-text">8. 参考资料</span></a></li></ol>
    
  </div>
</aside>
  
  <!-- Catalog END -->
</main>

<script>
  (function () {
    var url = 'http://example.com/2020/12/04/ElasticSearch之京东搜索实战/';
    var banner = ''
    if (banner !== '' && banner !== 'undefined' && banner !== 'null') {
      $('#article-banner').css({
        'background-image': 'url(' + banner + ')'
      })
    } else {
      $('#article-banner').geopattern(url)
    }
    $('.header').removeClass('fixed-header')

    // error image
    $(".markdown-content img").on('error', function() {
      $(this).attr('src', '/css/images/error_icon.png')
      $(this).css({
        'cursor': 'default'
      })
    })

    // zoom image
    $(".markdown-content img").on('click', function() {
      var src = $(this).attr('src')
      if (src !== '/css/images/error_icon.png') {
        var imageW = $(this).width()
        var imageH = $(this).height()

        var zoom = ($(window).width() * 0.95 / imageW).toFixed(2)
        zoom = zoom < 1 ? 1 : zoom
        zoom = zoom > 2 ? 2 : zoom
        var transY = (($(window).height() - imageH) / 2).toFixed(2)

        $('body').append('<div class="image-view-wrap"><div class="image-view-inner"><img src="'+ src +'" /></div></div>')
        $('.image-view-wrap').addClass('wrap-active')
        $('.image-view-wrap img').css({
          'width': `${imageW}`,
          'transform': `translate3d(0, ${transY}px, 0) scale3d(${zoom}, ${zoom}, 1)`
        })
        $('html').css('overflow', 'hidden')

        $('.image-view-wrap').on('click', function() {
          $(this).remove()
          $('html').attr('style', '')
        })
      }
    })
  })();
</script>


  <script>
    var qr = new QRious({
      element: document.getElementById('share-qrcode'),
      value: document.location.href
    });
  </script>






    <div class="scroll-top">
  <span class="arrow-icon"></span>
</div>
    <footer class="app-footer">
  <p class="copyright">
    &copy; 2024 | Proudly powered by <a href="https://hexo.io" target="_blank">Hexo</a>
    <br>
    Theme by <a target="_blank" rel="noopener" href="https://github.com/ltyeamin">tong.li</a>
  </p>
</footer>

<script>
  function async(u, c) {
    var d = document, t = 'script',
      o = d.createElement(t),
      s = d.getElementsByTagName(t)[0];
    o.src = u;
    if (c) { o.addEventListener('load', function (e) { c(null, e); }, false); }
    s.parentNode.insertBefore(o, s);
  }
</script>
<script>
  async("https://cdn.staticfile.org/fastclick/1.0.6/fastclick.min.js", function(){
    FastClick.attach(document.body);
  })
</script>

<script>
  var hasLine = 'true';
  async("https://cdn.staticfile.org/highlight.js/9.12.0/highlight.min.js", function(){
    $('figure pre').each(function(i, block) {
      var figure = $(this).parents('figure');
      if (hasLine === 'false') {
        figure.find('.gutter').hide();
      }
      hljs.configure({useBR: true});
      var lang = figure.attr('class').split(' ')[1] || 'code';
      var codeHtml = $(this).html();
      var codeTag = document.createElement('code');
      codeTag.className = lang;
      codeTag.innerHTML = codeHtml;
      $(this).attr('class', '').empty().html(codeTag);
      figure.attr('data-lang', lang.toUpperCase());
      hljs.highlightBlock(block);
    });
  })
</script>
<!-- Baidu Tongji -->



<script src='https://cdn.staticfile.org/mermaid/8.11.2/mermaid.min.js'></script>



<script src="/js/script.js"></script>


  </body>
</html>